package com.ruizhong.centercontroll.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.ruizhong.centercontroll.dao.TPageMapper;

import com.ruizhong.centercontroll.entity.*;
import com.ruizhong.centercontroll.server.WebSocketServer;

import com.ruizhong.centercontroll.service.*;
import com.ruizhong.centercontroll.util.WSResult;
import com.ruizhong.centercontroll.util.XmlPageMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.websocket.EncodeException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.*;
import java.util.*;

@Service
public class TPageServiceImpl extends ServiceImpl<TPageMapper, TPage> implements TPageService {
    @Override
    public Integer saveNewPage(TPage tPage) {
        String pageName = tPage.getPageName();
        List<TPage> list = lambdaQuery()
                .eq(TPage::getPageName, pageName)
                .list();
        if (!CollectionUtils.isEmpty(list)) {
            throw new RuntimeException("页面不可重复");
        }
        List<String> buttonGroupName = tPage.getButtonGroupName();
        if (!CollectionUtils.isEmpty(buttonGroupName)) {
            StringBuilder stringBuilder = new StringBuilder();
            for (String s : buttonGroupName) {
                stringBuilder.append(s + "#");
            }
            tPage.setButtonGroupNameData(stringBuilder.toString());
        }

        save(tPage);
        return tPage.getId();
    }

    @Override
    public HashMap<String, Object> getAllComponentByPageName(String pageName, Double aimPageWidth, Double aimPageHeight, Boolean display) throws JsonProcessingException {
        TPage tPage = getPageByPageName(pageName);
        Integer pageId = tPage.getId();
        Double pageWidth = tPage.getPageWidth();
        Double pageHeight = tPage.getPageHeight();

        if (pageId == null) {
            return (HashMap<String, Object>) Collections.EMPTY_MAP;
        }
        List<TButton> btns = tButtonService.getButtonsByPageId(pageId, pageWidth, pageHeight, aimPageWidth, aimPageHeight,display);
        List<TImage> images = tImageService.getImagesByPageId(pageId, pageWidth, pageHeight, aimPageWidth, aimPageHeight,display);
        List<TSlider> sliders = tSliderService.getSlidersByPageId(pageId, pageWidth, pageHeight, aimPageWidth, aimPageHeight,display);
        List<TSwitch> switches = tSwitchService.getSwitchsByPageId(pageId, pageWidth, pageHeight, aimPageWidth, aimPageHeight,display);
        List<TTextView> tTextViews = tTextViewService.getTextViewsByPageId(pageId, pageWidth, pageHeight, aimPageWidth, aimPageHeight,display);
        List<TVideo> tVideos = tVideoService.getVideosByPageId(pageId, pageWidth, pageHeight, aimPageWidth, aimPageHeight,display);
        List<TWebPage> tWebPages = tWebPageService.getWebPagesByPageId(pageId, pageWidth, pageHeight, aimPageWidth, aimPageHeight,display);
        List<TPPT> tppts = tpptService.getPPTsByPageId(pageId, pageWidth, pageHeight, aimPageWidth, aimPageHeight,display);
        List<T3DScene> t3DScenes = t3DSceneService.get3DsByPageId(pageId,pageWidth,pageHeight,pageHeight, aimPageWidth, aimPageHeight,display);
        HashMap<String, Object> resMap = new HashMap<>();
        resMap.put("buttonList", btns);
        resMap.put("imageList", images);
        resMap.put("sliderList", sliders);
        resMap.put("switchList", switches);
        resMap.put("textViewList", tTextViews);
        resMap.put("videoList", tVideos);
        resMap.put("webPageList",tWebPages);
        resMap.put("pptList",tppts);
        resMap.put("threeDList",t3DScenes);
        HashSet<String> buttonVariableSet = new HashSet<>();
        for (TButton btn : btns) {
            Set<String> returnVariableSet = btn.getReturnVariableSet();
            String beChangedVariableName = btn.getBeChangedVariableName();
            buttonVariableSet.addAll(returnVariableSet);
            buttonVariableSet.add(beChangedVariableName);
            btn.setReturnVariableSet(null);
            btn.setBeChangedVariableName(null);
        }


        HashSet<String> sliderVariableSet = new HashSet<>();
        HashMap<String, String> sliderVariableMap = new HashMap<>();
        for (TSlider slider : sliders) {
            sliderVariableSet.add(slider.getLastSlideName());
            sliderVariableSet.add(slider.getSliderVariable());
            sliderVariableSet.add(slider.getDisplayVariableName());
            if (slider.getSliderVariable() != null) {
                sliderVariableMap.put(slider.getSliderVariable(), slider.getLastSlideName());
            }
        }

        HashSet<String> videoVariableSet = new HashSet<>();
        for (TVideo tVideo : tVideos) {
            String displayVariableName = tVideo.getDisplayVariableName();
            String streamVariable = tVideo.getStreamVariable();
            if (!StringUtils.isEmpty(streamVariable))
                videoVariableSet.add(streamVariable);
            if (!StringUtils.isEmpty(displayVariableName))
                videoVariableSet.add(displayVariableName);
        }

        HashSet<String> webPageVariableSet = new HashSet<>();
        for (TWebPage tWebPage : tWebPages) {
            String displayVariableName = tWebPage.getDisplayVariableName();
            String webPageUrlVariable = tWebPage.getWebPageUrlVariable();
            if (!StringUtils.isEmpty(displayVariableName))webPageVariableSet.add(displayVariableName);
            if (!StringUtils.isEmpty(webPageVariableSet))webPageVariableSet.add(webPageUrlVariable);
        }

        HashSet<String> pptVariableSet = new HashSet<>();
        for (TPPT tppt : tppts) {
            String displayVariableName = tppt.getDisplayVariableName();
            String webPageUrlVariable = tppt.getPptUrlVariable();
            if (!StringUtils.isEmpty(displayVariableName))pptVariableSet.add(displayVariableName);
            if (!StringUtils.isEmpty(webPageVariableSet))pptVariableSet.add(webPageUrlVariable);
        }

        HashSet<String> switchVariableSet = new HashSet<>();
        for (TSwitch tSwitch : switches) {
            String displayVariableName = tSwitch.getDisplayVariableName();
            String switchVariable = tSwitch.getSwitchVariable();
            if (!StringUtils.isEmpty(displayVariableName))switchVariableSet.add(displayVariableName);
            if (!StringUtils.isEmpty(switchVariable))switchVariableSet.add(switchVariable);
        }


        resMap.put("buttonVariableSet", buttonVariableSet);
        resMap.put("sliderVariableSet", sliderVariableSet);
        resMap.put("sliderVariableMap", sliderVariableMap);
        resMap.put("videoVariableSet", videoVariableSet);
        resMap.put("switchVariableSet",switchVariableSet);
        resMap.put("pptVariableSet",pptVariableSet);
        return resMap;
    }

    private TPage getPageByPageName(String pageName) {
        TPage tPage = lambdaQuery()
                .eq(TPage::getPageName, pageName)
                .one();
        return tPage;
    }

    @Autowired
    private TAudioService tAudioService;

    @Override
    public void updatePage(TPage tPage) {
        final HashMap<Integer,List<Map<String,Object>>> pageAudioCommandList = new HashMap<>();
        List<TPage> list = lambdaQuery()
                .eq(TPage::getPageName, tPage.getPageName())
                .ne(TPage::getId, tPage.getId())
                .list();
        if (!CollectionUtils.isEmpty(list)) {
            throw new RuntimeException("页面名称不可重复");
        }
        List<String> buttonGroupName = tPage.getButtonGroupName();
        if (!CollectionUtils.isEmpty(buttonGroupName)) {
            StringBuilder stringBuilder = new StringBuilder();
            for (String s : buttonGroupName) {
                stringBuilder.append(s + "#");
            }
            tPage.setButtonGroupNameData(stringBuilder.toString());
        }
        lambdaUpdate()
                .eq(TPage::getId, tPage.getId())
                .set(TPage::getPageName, tPage.getPageName())
                .set(TPage::getPageWidth, tPage.getPageWidth())
                .set(TPage::getPageHeight, tPage.getPageHeight())
                .set(TPage::getHighestZIndex, tPage.getHighestZIndex())
                .set(TPage::getButtonGroupNameData, tPage.getButtonGroupNameData())
                .set(TPage::getPageBackgroundImage, tPage.getPageBackgroundImage())
                .set(TPage::getPageBackgroundColor,tPage.getPageBackgroundColor())
                .set(TPage::getPageImg,tPage.getPageImg())
                .update();
        List<TAudio> audioList = tPage.getAudioList();
        tAudioService.saveAudioList(audioList,tPage.getId());
    }

    @Override
    public List<TPage> getAllPages() {
        List<TPage> list = lambdaQuery()
                .select(TPage::getPageName, TPage::getId, TPage::getPageImg)
                .list();
        return list;
    }

    @Override
    @Transactional
    public void delPageByPageId(Integer pageId) {
        removeById(pageId);
        tButtonService.deleteButtonByPageId(pageId);
        tSwitchService.deleteSwitchByPageId(pageId);
        tImageService.deleteImagesByPageId(pageId);
        tTextViewService.deleteTextViewsByPageId(pageId);
        tSliderService.deleteSlidersByPageId(pageId);
    }

    @Override
    public void initPage(Integer pageId, String tokenId, Map<String, Object> variableMap, String clientIp) {
        List<TButton> buttonsByPageId = tButtonService.getButtonIdsByPageId(pageId);
        List<TSlider> sliderIdsByPageId = tSliderService.getSliderIdsByPageId(pageId);
        List<TVideo> videoIdsByPageId = tVideoService.getVideoIdsByPageId(pageId);
        List<TWebPage> webPageIdsByPageId = tWebPageService.getWebPageIdsByPageId(pageId);
        List<TSwitch> switchsByPageId = tSwitchService.getSwitchIdsByPageId(pageId);
        List<TImage> imagesByPageId = tImageService.getImageIdsByPageId(pageId);
        List<TTextView> tTextViewsByPageId = tTextViewService.getTextViewIdsByPageId(pageId);
        List<TPPT> pptsByPageId = tpptService.getPPTIdsByPageId(pageId);
        tCommandService.initPage(
                variableMap,
                buttonsByPageId,
                sliderIdsByPageId,
                videoIdsByPageId,
                webPageIdsByPageId,
                switchsByPageId,
                imagesByPageId,
                tTextViewsByPageId,
                pptsByPageId,
                tokenId,
                clientIp);
    }

    @Override
    public void updatePageImg(Map<String, String> conditionMap) {
        TPage tPage = new TPage();
        tPage.setId(Integer.parseInt(conditionMap.get("pageId")));
        tPage.setPageImg(conditionMap.get("imgData"));
        try {
            updateById(tPage);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public ResponseEntity<InputStreamResource> outputPage(String pageName) throws JsonProcessingException, JAXBException {
        TPage pageInfoByPageName = getPageInfoByPageName(pageName);
        Integer pageId = pageInfoByPageName.getId();
        Double pageWidth = pageInfoByPageName.getPageWidth();
        Double pageHeight = pageInfoByPageName.getPageHeight();
        Double aimPageWidth = pageWidth;
        Double aimPageHeight = pageHeight;
        List<TButton> btns = tButtonService.getButtonsByPageId(pageId, pageWidth, pageHeight, aimPageWidth, aimPageHeight, false);
        List<TImage> images = tImageService.getImagesByPageId(pageId, pageWidth, pageHeight, aimPageWidth, aimPageHeight, false);
        List<TSlider> sliders = tSliderService.getSlidersByPageId(pageId, pageWidth, pageHeight, aimPageWidth, aimPageHeight, false);
        List<TSwitch> switches = tSwitchService.getSwitchsByPageId(pageId, pageWidth, pageHeight, aimPageWidth, aimPageHeight, false);
        List<TTextView> tTextViews = tTextViewService.getTextViewsByPageId(pageId, pageWidth, pageHeight, aimPageWidth, aimPageHeight, false);
        List<TVideo> tVideos = tVideoService.getVideosByPageId(pageId, pageWidth, pageHeight, aimPageWidth, aimPageHeight, false);
        List<TWebPage> tWebPages = tWebPageService.getWebPagesByPageId(pageId, pageWidth, pageHeight, aimPageWidth, aimPageHeight, false);

        XmlPageMap xmlPageMap = new XmlPageMap();
        xmlPageMap.setButtonList(btns);
        xmlPageMap.setImageList(images);
        xmlPageMap.setSliders(sliders);
        xmlPageMap.setTSwitches(switches);
        xmlPageMap.setTTextViews(tTextViews);
        xmlPageMap.setTVideos(tVideos);
        xmlPageMap.setTWebPages(tWebPages);
        xmlPageMap.setPageInfo(pageInfoByPageName);
        JAXBContext context= JAXBContext.newInstance(
               XmlPageMap.class,
                TButton.class,
                TImage.class,
                TSlider.class,
                TSwitch.class,
                TTextView.class,
                TVideo.class,
                TWebPage.class,
                TPage.class
                );
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,Boolean.TRUE);
        StringWriter sw = new StringWriter();
        marshaller.marshal(xmlPageMap,sw);
        InputStreamResource resource = new InputStreamResource(new ByteArrayInputStream(sw.toString().getBytes()));
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DISPOSITION,"attachment;filename=component.xml");
        return ResponseEntity.ok()
                .headers(headers)
                .contentLength(sw.toString().getBytes().length)
                .contentType(MediaType.APPLICATION_XML)
                .body(resource);
    }

    @Override
    public XmlPageMap ImportPageXmlTemplate(MultipartFile file) {
        try(
                InputStream inputStream = file.getInputStream()
        ) {
            JAXBContext jaxbContext = JAXBContext.newInstance(XmlPageMap.class);
            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

            XmlPageMap xmlPageMap = (XmlPageMap) jaxbUnmarshaller.unmarshal(inputStream);
          return xmlPageMap;
        } catch (JAXBException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public TPage getPageInfoByPageName(String pageName) {
        TPage tPage = lambdaQuery()
                .eq(TPage::getPageName, pageName)
                .one();
        ArrayList<String> buttonGroupNameList = new ArrayList<>();
        String buttonGroupNameData = tPage.getButtonGroupNameData();
        if (!StringUtils.isEmpty(buttonGroupNameData)) {
            String[] split = buttonGroupNameData.split("#");
            for (String s : split) {
                buttonGroupNameList.add(s);
            }
            tPage.setButtonGroupName(buttonGroupNameList);
        } else {
            tPage.setButtonGroupName(Collections.EMPTY_LIST);
        }
//获取对应的audioList
        List<TAudio> audioList = tAudioService.getAudioListByPageId(tPage.getId());
        tPage.setAudioList(audioList);
        return tPage;
    }

    @Override
    public Integer getPageIdByPageName(String pageName) {
        TPage tPage = lambdaQuery()
                .eq(TPage::getPageName, pageName)
                .one();
        if (tPage == null) {
            return null;
        }

        return tPage.getId();
    }

    @Autowired
    private TButtonService tButtonService;

    @Autowired
    private TSwitchService tSwitchService;

    @Autowired
    private TSliderService tSliderService;

    @Autowired
    private TImageService tImageService;

    @Autowired
    private TTextViewService tTextViewService;

    @Autowired
    private TCommandService tCommandService;

    @Autowired
    private TVideoService tVideoService;

    @Autowired
    private TWebPageService tWebPageService;

    @Autowired
    private TPPTService tpptService;

    @Autowired
    private T3DSceneService t3DSceneService;

    @Override
    @Transactional
    public void saveAllComponents(Map<String, List<Map<String, Object>>> conditionMap, Integer pageId, String token,boolean isNew) {
        List<Map<String, Object>> buttonList = conditionMap.get("buttonList");
        List<Map<String, Object>> switchList = conditionMap.get("switchList");
        List<Map<String, Object>> sliderList = conditionMap.get("sliderList");
        List<Map<String, Object>> imageList = conditionMap.get("imageList");
        List<Map<String, Object>> textList = conditionMap.get("textList");
        List<Map<String, Object>> videoList = conditionMap.get("videoList");
        List<Map<String, Object>> webPageList = conditionMap.get("webPageList");
        List<Map<String, Object>> pptList = conditionMap.get("pptList");
        List<Map<String, Object>> threeDMeshList = conditionMap.get("threeDMeshList");
        List<Map<String, Object>> threeDSceneList = conditionMap.get("threeDSceneList");
        List<Map<String, Object>> threeDSourceList = conditionMap.get("threeDSourceList");

        tButtonService.saveNewButtonList(buttonList, pageId,isNew);

        tSwitchService.saveNewSwitchList(switchList, pageId,isNew);

        tSliderService.saveNewSliderList(sliderList, pageId,isNew);
        tImageService.saveNewImageList(imageList, pageId,isNew);
        tTextViewService.saveNewTextList(textList, pageId,isNew);
        tVideoService.saveNewVideoList(videoList, pageId,isNew);
        tWebPageService.saveNewWebPageList(webPageList,pageId,isNew);
        tpptService.saveNewPPTList(pptList,pageId,isNew);
        t3DSceneService.saveNew3DList(threeDSceneList,threeDMeshList,threeDSourceList,pageId,isNew);
        new Thread(new Runnable() {
            @Override
            public void run() {
                String pageName = getById(pageId).getPageName();
                Set<String> list = WebSocketServer.pathMapClient.get(pageName);
                if (CollectionUtils.isEmpty(list)) {
                    return;
                }
                WSResult<HashMap<String, String>> reFreshMes = new WSResult<>();
                HashMap<String, String> resMap = new HashMap<>();
                resMap.put("type","refresh");
//                resMap.put("")
                reFreshMes.setData(resMap);
                for (String wsId : list) {
                    if (wsId.equals(token)){
                        continue;
                    }
                    try {
                        WebSocketServer.sendInfo(reFreshMes, wsId);
                    } catch (IOException e) {
                        e.printStackTrace();
                    } catch (EncodeException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
}
